#ifndef MAINWINDOW_H
#define MAINWINDOW_H

//openCV
#ifdef _WIN32 //windows
#include <cv.h>
#include <highgui.h>
#include <windows.h>
#include <process.h>
#else //linux
#include <opencv/cv.h>
#include <opencv/highgui.h>
#endif

//Generic Imports
#include <QtGui/QMainWindow>
#include <QFile>
#include <iostream>
#include "ui_mainwindow.h"
#include "ui_preferences.h"
#include "ui_aboutbox.h"
#include "searchwindow.h"
#include "preferences.h"
#include "aboutbox.h"
#include <QMessageBox>
#include <QShortcut>
#include <QtDebug>
#include <algorithm>
#include "gesturerecognition.h"

//Camera and Video specific includes
#include <QWidget>
#include <QVBoxLayout>
#include "WebcamVideoPlayer.h"
#include <Phonon/VideoWidget>
#include <Phonon/MediaObject>
#include <QDir>
#include <QPixmap>
#include <QTimer>
#include <QList>
#include <QTime>

// backend classes
//Debug imports
#include "includes/lesson.h"
#include <QDebug>
#include "includes/thesaurus.h"
#include "includes/user.h"
#include "includes/usercollection.h"
#include "includes/progressitem.h"

// user admin dialog
#include "qusersdialog.h"
// quiz widget
#include "quizwidget.h"
#include "quiziconwidget.h"

namespace Ui
{
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
private:
    /* Declarations of variables
     * Variables declarations are split into areas for readability
     * and logicalness.
     */

    //Generic variable
    Ui::MainWindow *ui;
    enum ProgramState {welcomeState = 0, userState = 1, cartoonState, instructorPausedState, instructorPlayingState, nowWhatState,
                       nowWhatAfterRecordingState, recordingState,
                       comparingInstructorPausedState, comparingInstructorPlayingState, comparingRecordingPausedState,
                       comparingRecordingPlayingState, ratingState, quizState, loadingState, loadingState_recording, viewingProgressState};
    ProgramState state;

    //Webcam variables
    WebcamVideoPlayer *webcam;
    CvCapture *camera;    
    int hSize;
    int wSize;    
    bool hasCamera; //whether a web cam is available

    //video recording
    int frameCounter;
    bool flashRecordingSquare;
    CvVideoWriter *writer;
    QProcess *ffmpeg;
    bool buildingVideo;
    int vidQuality;
    int frameRate;
    QString frameExtension;
    int maxTime;
    QTime videoTimer;

    //Video player
    QString image_filename;
    QString demoVideo_filename;
    QString userVideo_filename;
    QString dir;
    Phonon::MediaObject *clip;

    int frameRateOffseter;    

    //User variables
    int userRating;
    UserCollection userCollection;
    ProgressItem currentProgress;
    User currentUser;
    QTime phraseStartTime;

    //Search window
    SearchWindow searchEngine;

    //Settings dialog
    Ui_Dialog uip;
    Preferences preferenceWindow;
    void saveSettings();
    void loadSettings();

    QSettings mainSettings;

    //About Box dialog
    Ui_AboutBox uia;
    AboutBox aboutBox;

    //the all powerfull, all mighty QTimer (without which all program life would end)
    QTimer *timer;

    // thesaurus object
    Thesaurus thesaurus;

    //Gesture recognition    
    GestureRecognition *gestureTopLeft;
    GestureRecognition *gestureTopRight;
    bool gesturesEnabled;
    bool topLeftEnabled;
    bool topRightEnabled;
   //images
    QImage topLeftImage;
    QImage topRightImage;

    //lesson variables

    // lessons and all phrases exist here in memory
    QList<Lesson> lessons;
    // the index of the currently taught phrase from the current lesson
    QList<Phrase>::iterator currentPhrase;
    // pointer to the current lesson
    QList<Lesson>::iterator currentLesson;

    // master list of all phrases!
    PhraseCollection phrases;

    bool withinLesson;

    //status bar variable
    QLabel* userLabel;
    QLabel* actionLabel;

    QuizWidget *quizWidget;
    Phonon::Path path;

    // actions which open a lesson
    QList<QAction*> lessonActions;

    // ACTIONS ////////////////////////////////////////////////////////

    /**
     * Present the user with a quiz immediately.
     */
    QAction* quizMeAction;

    // HELPER METHODS /////////////////////////////////////////////////
private:
    /**
     * Initialise the back end. This includes scanning the 'lessons'
     * directory, parsing the XML, populating the file menu and
     * lesson collection with Lesson objects, reading all the phrases
     * in the lessons into the phrase collection, linking the phrases
     * to their lessons and feeding all the phrases to the thesaurus
     */
    void init();
    void createStatusBar();

public:
    MainWindow(QWidget *parent = 0);
    void startConnections();  
    ~MainWindow();

    /**
     * Sets the program state.
     */
    void setState(ProgramState newState);

    // present a single phrase from the current lesson to the user
    void presentPhrase(Phrase& phrase);

    // present the next phrase from the current lesson to the user;
    // returns 'true' if the lesson is OVER!
    bool presentNextPhrase();

    // enum listing various content phonon can play
    enum VideoSources {DemoVideo = 0, UserVideo};

    // places phonon widget can occupy in gui
    enum VideoPositions {TopLeft = 0, BottomRight};

    /**
     * Create menu items. Note that many additional menu
     * items live in the designer form.
     */
    void createMenu();

    // MUTATORS ///////////////////////////////////////////////

    /**
     * Use these methods to change 'global' filenames.
     * @param f Filename for instructor video in '/videos/'
     */
    void setDemoVideoFilename(const QString& f);
    /**
     * Use these methods to change 'global' filenames.
     * @param f Filename for cartoon hint image in '/cartoons/'
     */
    void setCartoonFilename(const QString& f);

    /**
     * Set the video source for the Phonon widget.
     * @param MainWindow::VideoSources src Enum type specifying whether
     * video should be the instructor video for the lesson or the user
     * video.
     */
    void setVideo(MainWindow::VideoSources src);

    /**
     * Display the video in the top/left stacked widget or in the bottom/right
     * stacked widget, depending on orientation. Reparents the Phonon widget.
     * @param MainWindow::VideoPositions pos Enum indicating where the video
     * should be positioned.
     * @return 'True' if the Phonon widget was moved; 'False' if it was already in
     * desired position.
     */
    bool setVideoPosition(const MainWindow::VideoPositions& pos);

    /**
     * Clears out the temporary directory where the construction frames might have been.
     */
    void clearTempDir();

public slots:
    //slots that are attached to events (signals)
    void play();
    void replayInstructor();
    void stop();
    void videoFinished();
    void find();
    void okClicked();
    void updateInterval();
    void record();
    void topStackClicked();
    void comparing();
    void showCartoon();
    void showAboutBox();
    void showUserScreen();
    void changeView();
    void quizDone();
    void gestureDetected(int id);
    void skipPhrase();
    bool previousPhrase();

    //User related
        // select user
        void signInUser(QString name);
        void userAccountClicked();
        // rating
        void showHowDidIDo();
        void rating_ok();
        void rating_happy();
        void rating_sad();
        void openProgressViewer();
        void openProgressViewerFiltered();//now filters by username
        //showing
        void playVideo(QTreeWidgetItem* it, int col);
        // saving
        void saveUserProgress();
        void saveUsers();



    void lessonSelected();
    void openLesson();

    void showPreferences();
    //Process slots
    void ffmpegFinished(int exitCode, QProcess::ExitStatus exitStatus);
    //Preferences Dialog slots
    void videoQualityChanged(int val);
    void videoFrameRateChanged(int val);
    void videoFrameFormatChanged(QString extension);
    void maxRecordingLengthChanged(int val);
    void preferencesClosed(int code);
    void gesturesEnabledChanged(bool enabled);
    void sensitivityChanged(double sensitivity);

private slots:
    /**
     * Phonon Media Object widget state changed.
     */
    void phononStateChanged(const Phonon::State newState, const Phonon::State oldState);

    /**
     * 'Quiz me' action selected.
     */
    void quizMeClicked();

    /**
     * User selected correct quiz answer.
     */
    void quizCorrect();

    /**
     * User selected incorrect quiz answer.
     */
    void quizWrong();

    /**
     * Quiz cleanup. Called once user selects any answer
     * TODO: move to setState().
     * Return phonon widget to top.
     */
    void quizCleanup();

    void recentPhraseClicked(QModelIndex index);
};

#endif // MAINWINDOW_H
